package report

import (
	"context"
	"encoding/json"
	"fmt"
	"git.mycaigou.com/gfyx/common/authorize"
	"git.mycaigou.com/gfyx/common/http_client"
	"git.mycaigou.com/gfyx/common/simplecopier"
	reportDto "git.mycaigou.com/gfyx/micro-gfyx-mp-api/http_server/dto/report"
	"git.mycaigou.com/gfyx/micro-gfyx-mp-api/infrastructure/common/constants"
	"git.mycaigou.com/gfyx/micro-gfyx-mp-api/infrastructure/repository/business_opportunity"
	"git.mycaigou.com/gfyx/micro-gfyx-mp-api/infrastructure/utils"
	"git.mycaigou.com/gfyx/micro-gfyx-mp-api/infrastructure/utils/ossfile"
	businessOpportunityPb "git.mycaigou.com/gfyx/micro-gfyx-mp-api/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/business_opportunity"
	cluePb "git.mycaigou.com/gfyx/micro-gfyx-mp-api/proto/micro_gfyx_oppty_service_proto/micro-gfyx-oppty-service/clue"
	micro_gfyx_user_service "git.mycaigou.com/gfyx/micro-gfyx-mp-api/proto/micro_gfyx_user_service_proto/micro-gfyx-user-service"
	"git.myscrm.cn/golang/stark/v4"
	"github.com/gin-gonic/gin"
	"strings"
)

type ReportService struct {
	reportRepo             ReportRepositoryIface
	reportFollowRepository ReportFollowRepositoryIface
	//opportunityRepo        bid.BusinessOpportunityRepositoryIface
}

// NewReportService
// 创建构造函数
func NewReportService(reportRepo ReportRepositoryIface,
	//opportunityRepo bid.BusinessOpportunityRepositoryIface,
	reportFollowRepository ReportFollowRepositoryIface) ReportServiceIface {
	return &ReportService{
		reportRepo: reportRepo,
		//opportunityRepo:        opportunityRepo,
		reportFollowRepository: reportFollowRepository,
	}
}

func (s *ReportService) SetSharerCodeWithReportUrl(ctx *gin.Context, urlUid string) error {
	request := &reportDto.ReportInfoRequestDto{
		Code: urlUid,
	}
	res, err := s.reportRepo.ReportInfo(ctx, request)

	if err != nil {
		return err
	}

	utils.SetLoginContext(ctx, authorize.GetGlobalUserId(ctx), res.TenantCode, res.SharerUserCode)

	return nil
}

func (s *ReportService) SetTenantCodeWithReportUrl(ctx *gin.Context, urlUid string) error {
	request := &reportDto.ReportInfoRequestDto{
		Code: urlUid,
	}
	res, err := s.reportRepo.ReportInfo(ctx, request)

	if err != nil {
		return err
	}

	if res.TenantCode == "" {
		return fmt.Errorf("非付费用户必须传递报备链接ID")
	}

	ctx.Set(authorize.TENANT_CODE_KEY, res.TenantCode)

	return nil
}

func (s *ReportService) GetFormTemplateConfig(ctx context.Context, templateId string) ([]map[string]interface{}, error) {
	templateList, err := s.reportRepo.GetFormTemplateConfig(ctx, templateId)
	if err != nil {
		return nil, err
	}

	// 数据格式转换，空值补充
	if templateList != nil {
		for key, temp := range templateList {
			//分组处理
			groupKey := temp["field_name"].(string)
			temp["field_component"] = "Group"
			fieldComponentProps := temp["field_component_props"].(string)
			var groupFieldPropsMap map[string]interface{}
			err := json.Unmarshal([]byte(fieldComponentProps), &groupFieldPropsMap)
			if err != nil {
				stark.Logger.Errorf(ctx, "模板配置json解析失败，key:%s,value:%s", groupKey, fieldComponentProps)
				return nil, err
			}
			temp["field_component_props"] = groupFieldPropsMap
			if _, ok := temp["sort"]; !ok {
				temp["sort"] = 0
			}
			//if _, ok := temp["field_name"]; !ok {
			//	temp["field_name"] = ""
			//}
			delete(temp, "field_name") //前端要求删除group field_name
			//filed 字段处理
			if _, ok := temp["children"]; ok {
				childrenList := make([]map[string]interface{}, len(temp["children"].([]interface{})))
				for i, item := range temp["children"].([]interface{}) {
					if itemMap, ok := item.(map[string]interface{}); ok {
						childrenList[i] = itemMap
					} else {
						stark.Logger.Errorf(ctx, "模板配置分组children格式错误，解析失败，key:%s,value:%s", groupKey, temp["children"])
					}
				}
				for k, children := range childrenList {
					childKey := children["field_name"].(string)
					childFieldComponentProps := children["field_component_props"].(string)
					var childFieldPropsMap map[string]interface{}
					err := json.Unmarshal([]byte(childFieldComponentProps), &childFieldPropsMap)
					if err != nil {
						stark.Logger.Error(ctx, "模板配置json解析失败，gropy_key:%s,child_key:%s,value:%s", groupKey, childKey, childFieldComponentProps)
						return nil, err
					}
					children["field_component_props"] = childFieldPropsMap
					if _, ok := children["sort"]; !ok {
						children["sort"] = 0
					}
					if _, ok := children["is_default"]; !ok {
						children["is_default"] = 0
					}
					if _, ok := children["required"]; !ok {
						children["required"] = 0
					}
					if _, ok := children["field_component"]; !ok {
						children["field_component"] = ""
					}
					if _, ok := children["field_name"]; !ok {
						children["field_name"] = ""
					}
					childrenList[k] = children
				}

				temp["children"] = childrenList
			}
			templateList[key] = temp
		}
	}

	return templateList, nil
}

func (s *ReportService) GetFormDataRule(ctx context.Context, key string) (map[string]interface{}, error) {
	ruleList, err := s.reportRepo.GetFormDataRule(ctx, key)
	if err != nil {
		return nil, err
	}
	result := make(map[string]interface{}, 0)
	if ruleList != nil {
		for _, item := range ruleList {
			ruleKey := item["rule_key"].(string)
			ruleValueStr := item["rule_value"].(string)

			// 解析ruleValue字段的值为map[string]interface{}
			var ruleValueMap map[string]interface{}
			err := json.Unmarshal([]byte(ruleValueStr), &ruleValueMap)
			if err != nil {
				stark.Logger.Error(ctx, "数据规则json解析失败，key:%s,value:%s", ruleKey, ruleValueStr)
				return nil, err
			}
			item["rule_value"] = ruleValueMap
			result[ruleKey] = ruleValueMap
			//ruleList[key] = item
		}
	}
	return result, nil
}

func (s *ReportService) GetReportUserList(ctx context.Context) (map[string]interface{}, error) {
	//TODO implement me
	list, err := s.reportRepo.GetUserList(ctx)
	if err != nil {
		return nil, err
	}
	return list, nil
}

func (s *ReportService) GenerateUrl(ctx context.Context, rs *ReportShare) (string, error) {
	//生成分享链接
	code, err := s.reportRepo.GenerateUrl(ctx, rs)
	if err != nil {
		return "", err
	}

	//更新数据状态
	statusRequest := &businessOpportunityPb.UpdateOpptyStatusRequest{
		DataSource:   rs.ClueSource,
		DataSourceId: rs.ClueSourceId,
		Status:       constants.OpptyStatusShare,
		FromDevice:   constants.FromDeviceClueMini,
	}
	_, errStatus := business_opportunity.NewOpptyStatusRepository().UpdateOpptyStatus(ctx, statusRequest)
	if errStatus != nil {
		stark.Logger.Error(ctx, "UpdateOpptyStatus err:", errStatus)
		return "", err
	}

	return code, nil
}

func (s *ReportService) ReceiveUrl(ctx context.Context, userId, code string) (bool, error) {
	return s.reportRepo.ReceiveUrl(ctx, userId, code)
}

func (s *ReportService) ReportList(ctx context.Context, condition *reportDto.ReportFromSharingListRequestDto) (int64, []*micro_gfyx_user_service.ReportFromSharing, error) {

	return s.reportRepo.ReportFromSharingList(ctx, condition)

}

func (s *ReportService) ReportInfo(ctx context.Context, condition *reportDto.ReportInfoRequestDto) (*micro_gfyx_user_service.ReportFromSharing, error) {
	return s.reportRepo.ReportInfo(ctx, condition)
}

func (s *ReportService) SearchContacts(ctx context.Context, condition *reportDto.ReportOptionRequest) (*http_client.BigDataResponse, error) {
	request := &reportDto.SearchContactRequest{
		PageNum:  condition.Page,
		PageSize: condition.PageSize,
		Keyword:  condition.Keyword,
	}

	if condition.ClueSource == "WINBID" {
		// 中标时，取开发商和供应商
		request.DeveloperOrganizingCode = condition.OrganizingCode
	} else if condition.ClueSource == "SUPPLIER" {
		// 工程单位时，取工程单位联系方式
		request.SupplierOrganizingCode = condition.OrganizingCode
	} else {
		// 其它时候，取开发商联系方式
		request.DeveloperOrganizingCode = condition.OrganizingCode
		request.CompanyCategory = "开发商"
	}

	return s.reportRepo.SearchContacts(ctx, request)
}

func (s *ReportService) GetTeamLeader(ctx context.Context, reportId string) (map[string]interface{}, error) {
	result, err := s.reportRepo.GetTeamLeader(ctx, reportId)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (s *ReportService) FillReportForm(ctx context.Context, params *reportDto.FillReportFormRequest) (map[string]interface{}, error) {
	res := map[string]interface{}{}

	params.ClueSource = strings.ToLower(params.ClueSource)

	if params.ClueSource == "clue" {
		data, err := s.reportRepo.GetReportSourceInfo(ctx, "CLUE", params.ClueSourceId)
		if err != nil {
			return nil, err
		}

		res = data
	} else {
		data, err := s.reportRepo.FillReportForm(ctx, params)

		if err != nil {
			return res, err
		}

		if len(data.Data) <= 0 {
			return res, fmt.Errorf("%s %s 找不到相应数据", params.ClueSource, params.ClueSourceId)
		}
		res = data.Data[0]
	}

	return res, nil
}

func (s *ReportService) GetReport(ctx context.Context, reportId string) (map[string]interface{}, error) {
	report, err := s.reportRepo.GetReport(ctx, reportId)
	if err != nil {
		return nil, err
	}
	data, err := simplecopier.StructToMapByJsonTag(report)
	if err != nil {
		return nil, err
	}
	// 图片转成oss链接
	if value, ok := data["project_image"]; ok {
		imageList := make([]string, 0)
		if image, ok := value.(string); ok && image != "" {
			images := strings.Split(image, ",")
			for _, item := range images {
				url, err := ossfile.GetSignURL(item)
				if err != nil {
					stark.Logger.Errorf(ctx, "ossfile.GetSignURL err: %s | item: %s", err, item)
					continue
				}
				imageList = append(imageList, url)
			}
		}
		data["project_image"] = imageList
	}

	return data, nil
}

func (s *ReportService) SaveFollowRecord(ctx context.Context, request *reportDto.SaveFollowRecordRequest) error {
	return s.reportFollowRepository.SaveFollowRecord(ctx, request)
}

func (s *ReportService) GetFollowRecordList(ctx context.Context, reportId string, page int32, pageSize int32) ([]map[string]interface{}, int64, error) {
	list := make([]map[string]interface{}, 0)
	followRecord, err := s.reportFollowRepository.GetFollowRecordList(ctx, reportId, page, pageSize)
	if err != nil {
		return list, 0, err
	}

	if followRecord != nil && followRecord.GetList() != nil {
		for _, item := range followRecord.GetList() {
			// 获取oss的图片链接
			if item.Images != nil {
				for index, image := range item.Images {
					imageUrl, err := ossfile.GetSignURL(image)
					if err != nil {
						stark.Logger.Errorf(ctx, "GetFollowRecordList ossfile.GetSignURL image:%s, err: %s", image, err)
					} else {
						item.Images[index] = imageUrl
					}
				}
			}
		}
		list, err = simplecopier.SliceStructToSliceMapByJsonTag(followRecord.GetList())
		if err != nil {
			return list, 0, err
		}
		return list, followRecord.GetTotal(), nil
	}
	return list, 0, nil
}

// Save 保存报备信息
func (s *ReportService) Save(ctx context.Context, saveReq *reportDto.SaveRequest) (bool, string, error) {
	flag, reportId, err := s.reportRepo.Save(ctx, saveReq)
	if err != nil {
		return false, "", err
	}
	return flag, reportId, nil
}

// GetMyReportList 获取我的线索
func (s *ReportService) GetMyReportList(ctx context.Context, requestDto *reportDto.ReportMyListRequestDto) (*reportDto.ReportMyListResponseDto, error) {
	result := reportDto.ReportMyListResponseDto{
		List: []reportDto.ReportListItem{},
	}
	remoteRes, err := s.reportRepo.GetReportList(ctx, requestDto)
	if err != nil {
		return nil, err
	}
	result.Page = requestDto.Page
	result.PageSize = requestDto.PageSize
	result.Total = int(remoteRes.Total)

	if remoteRes.List != nil {
		for _, item := range remoteRes.List {
			result.List = append(result.List, reportDto.ReportListItem{
				UID:                   item.Uid,
				ProjectTitle:          item.ProjectTitle,
				FollowStatus:          int(item.FollowStatus),
				Submitter:             item.Submitter,
				CompanyName:           item.CompanyName,
				ResponsiblePersonName: item.ResponsiblePersonName,
				ResponsiblePersonGUID: item.ResponsiblePersonGuid,
				AgencyName:            item.AgencyName,
				AgencyContact:         item.AgencyContact,
				ProjectProvinceCode:   item.ProjectProvinceCode,
				ProjectCityCode:       item.ProjectCityCode,
				CreatedOn:             item.CreatedOn,
				ModifiedOn:            item.ModifiedOn,
			})
		}
	}

	return &result, nil
}

func (s *ReportService) GetRegionReportList(ctx *gin.Context, requestDto *reportDto.ReportMyListRequestDto) (*reportDto.ReportMyListResponseDto, error) {
	result := reportDto.ReportMyListResponseDto{
		List: []reportDto.ReportListItem{},
	}
	if requestDto.SubmitStartTime != "" && requestDto.SubmitEndTime != "" {
		requestDto.SubmitStartTime = requestDto.SubmitStartTime + " 00:00:00"
		requestDto.SubmitEndTime = requestDto.SubmitEndTime + " 23:59:59"
	}
	remoteRes, err := s.reportRepo.GetRegionReportList(ctx, requestDto)
	if err != nil {
		return nil, err
	}
	result.Page = requestDto.Page
	result.PageSize = requestDto.PageSize
	result.Total = int(remoteRes.Total)

	if remoteRes.List != nil {
		for _, item := range remoteRes.List {
			result.List = append(result.List, reportDto.ReportListItem{
				UID:                   item.Uid,
				ProjectTitle:          item.ProjectTitle,
				FollowStatus:          int(item.FollowStatus),
				Submitter:             item.Submitter,
				CompanyName:           item.CompanyName,
				ResponsiblePersonName: item.ResponsiblePersonName,
				ResponsiblePersonGUID: item.ResponsiblePersonGuid,
				AgencyName:            item.AgencyName,
				AgencyContact:         item.AgencyContact,
				CreatedOn:             item.CreatedOn,
				ModifiedOn:            item.ModifiedOn,
			})
		}
	} else {
		remoteRes.List = make([]*cluePb.ReportInfo, 0)
	}

	return &result, nil
}

func (s *ReportService) GetReportStat(ctx context.Context) (*reportDto.MyReportStatResponse, error) {
	report, err := s.reportRepo.GetReportStat(ctx)
	if err != nil {
		return nil, err
	}
	reportData := reportDto.ReportData{
		FollowCnt: report.FollowCnt,
		SignCnt:   report.SignCnt,
		NoSignCnt: report.NoSignCnt,
	}

	result := &reportDto.MyReportStatResponse{
		Report: reportData,
	}
	return result, nil
}

func (s *ReportService) UpdateReportShare(ctx context.Context, userUid string, code string, data *micro_gfyx_user_service.ReportFromSharing) (bool, error) {
	return s.reportRepo.UpdateReportShare(ctx, userUid, code, data)
}
